﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using DiracTCC.Business;
using System.Threading;

namespace DiracTCC.WinForm
{
    public partial class ProcessImages : Form
    {
        private string videoPath;
        private string instPath;
        private VideoInfo video;
        private int progressValue = 0;
        private YuvToBmpConverter originalVideo;
        private YuvToBmpConverter codedVideo;

        private bool isInstrumentation;
        private string instVideoPath;
        private Queue<string> argQueue;

        private Form1 BaseForm;

        public event EventHandler FinishedProcessing;

        public ProcessImages()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Start the processing to convert videos generated by
        /// DIRAC to BMP files. This overload process original and
        /// generated videos.
        /// </summary>
        /// <param name="path">Path to the YUV video file</param>
        /// <param name="video">YUV video info</param>
        public void StartProcessing(string path, VideoInfo video, Form1 form)
        {
            StartProcessing(path, video, false, form);
        }

        public void StartProcessing(string path, VideoInfo video, string[] instrumentationArguments, Form1 form)
        {
            progressBar1.Maximum = video.NumberOfFrames * instrumentationArguments.Count() * 2 + 2;
            progressBar1.Value = (int)Math.Ceiling(progressBar1.Maximum * 0.2);
            Application.DoEvents();

            argQueue = new Queue<string>();
            instVideoPath = path;

            BaseForm = form;

            foreach (var argument in instrumentationArguments)
            {
                argQueue.Enqueue(argument);
            }
            this.video = video;

            var inst = new InstrumentationGenerator();
            inst.VideoCreated += new EventHandler(inst_VideoCreated);
            this.instPath = inst.CreateYuvVideo(
                            instVideoPath,
                            argQueue.Dequeue(),
                            "Helpers");
        }

        public void ProcessNextArgument()
        {
            if (argQueue.Count > 0)
            {
                var inst = new InstrumentationGenerator();
                inst.VideoCreated += new EventHandler(inst_VideoCreated);
                this.instPath = inst.CreateYuvVideo(
                                instVideoPath,
                                argQueue.Dequeue(),
                                "Helpers");
            }
            else
            {
                CallOriginalForm f = new CallOriginalForm(CloseForm);
                BaseForm.Invoke(f);
            }
        }

        public void inst_VideoCreated(object sender, EventArgs e)
        {
            CallStartProcessing c = new CallStartProcessing(StartProcessing);
            BaseForm.Invoke(c, instPath, video, true, BaseForm);
        }

        // delegate stuff
        public delegate void CallStartProcessing(string path, VideoInfo video, bool instrumentation, Form1 baseForm);

        /// <summary>
        /// Start the processing to convert all videos generated by
        /// DIRAC to BMP files. 
        /// </summary>
        /// <param name="path">Path to the YUV video file</param>
        /// <param name="video">YUV video info</param>
        private void StartProcessing(string path, VideoInfo video, bool instrumentation, Form1 baseForm)
        {
            this.videoPath = path;
            this.video = video;
            this.isInstrumentation = instrumentation;
            this.BaseForm = baseForm;

            // set progress bar size
            if(!isInstrumentation)
            {
                progressBar1.Maximum = video.NumberOfFrames * 4 + 2;
            }

            originalVideo = new YuvToBmpConverter(video, @"Helpers");
            originalVideo.ConvertToRGBCompleted += new EventHandler(originalVideo_ConvertToRGBCompleted);
            originalVideo.ConvertToBMPCompleted += new EventHandler(originalVideo_ConvertToBMPCompleted);
            originalVideo.NewFrameConvertedToRGB += new EventHandler(originalVideo_NewFrameConvertedToRGB);
            originalVideo.NewFrameConvertedToBMP += new EventHandler(originalVideo_NewFrameConvertedToBMP);


            originalVideo.ConvertToRGB(path);
        }

        // original video
        void originalVideo_NewFrameConvertedToBMP(object sender, EventArgs e)
        {
            progressValue++;
            CallOriginalForm d = new CallOriginalForm(SetControlPropertyValue);
            BaseForm.Invoke(d);
        }
        void originalVideo_NewFrameConvertedToRGB(object sender, EventArgs e)
        {
            progressValue++;
            CallOriginalForm d = new CallOriginalForm(SetControlPropertyValue);
            BaseForm.Invoke(d);
        }
        void originalVideo_ConvertToBMPCompleted(object sender, EventArgs e)
        {
            //CallOriginalForm f = new CallOriginalForm(CloseForm);
            //BaseForm.Invoke(f);

            if (isInstrumentation)
            {
                ProcessNextArgument();
            }
            else
            {
                codedVideo = new YuvToBmpConverter(video, @"Helpers");
                codedVideo.ConvertToRGBCompleted += new EventHandler(codedVideo_ConvertToRGBCompleted);
                codedVideo.ConvertToBMPCompleted += new EventHandler(codedVideo_ConvertToBMPCompleted);
                codedVideo.NewFrameConvertedToRGB += new EventHandler(codedVideo_NewFrameConvertedToRGB);
                codedVideo.NewFrameConvertedToBMP += new EventHandler(codedVideo_NewFrameConvertedToBMP);

                codedVideo.ConvertToRGB(videoPath + ".localdec.yuv");
            }
        }
        void originalVideo_ConvertToRGBCompleted(object sender, EventArgs e)
        {
            originalVideo.ConvertToBMP(
                YuvToBmpConverter.GetBMPPath(videoPath), 
                Path.ChangeExtension(videoPath, "rgb"));
        }

        // coded video
        void codedVideo_NewFrameConvertedToBMP(object sender, EventArgs e)
        {
            progressValue++;
            CallOriginalForm d = new CallOriginalForm(SetControlPropertyValue);
            BaseForm.Invoke(d);
        }
        void codedVideo_NewFrameConvertedToRGB(object sender, EventArgs e)
        {
            progressValue++;
            CallOriginalForm d = new CallOriginalForm(SetControlPropertyValue);
            BaseForm.Invoke(d);
        }
        void codedVideo_ConvertToBMPCompleted(object sender, EventArgs e)
        {
            CallOriginalForm f = new CallOriginalForm(CloseForm);
            BaseForm.Invoke(f);
        }
        void codedVideo_ConvertToRGBCompleted(object sender, EventArgs e)
        {
            codedVideo.ConvertToBMP(
                YuvToBmpConverter.GetBMPPath(videoPath + ".localdec.yuv"),
                videoPath + ".localdec.rgb");
        }


        // stuff to access the form!
        public delegate void CallOriginalForm();
        public void SetControlPropertyValue()
        {
            if(progressBar1.Value + 1 < progressBar1.Maximum)
                progressBar1.Value += 1;
        }
        public void CloseForm()
        {
            try
            {
                this.Close();

                if (FinishedProcessing != null)
                    FinishedProcessing(this, new EventArgs());
            }
            catch (Exception)
            {
                
                //throw;
            }
        }

        private void ProcessImages_Load(object sender, EventArgs e)
        {

        }
    }
}
